use std::time::Duration;
use anyhow::Result;
use async_trait::async_trait;
use protoactor_rs::{
    actor::{Actor, ActorContext, ActorError, Props},
    system::ActorSystem,
    middleware::LoggingMiddleware,
    supervision::Strategies,
    dispatcher::Dispatchers,
};

// 测试用的消息
#[derive(Debug)]
struct Ping(usize);

#[derive(Debug)]
struct Pong(usize);

// 测试用的 Actor
struct TestActor {
    id: String,
}

#[async_trait]
impl Actor for TestActor {
    type Context = ActorContext;

    async fn receive(&self, ctx: &mut Self::Context, msg: Box<dyn std::any::Any + Send>) -> Result<(), ActorError> {
        if let Ok(ping) = msg.downcast::<Ping>() {
            println!("[{}] Received Ping({})", self.id, ping.0);
            ctx.respond(Pong(ping.0));
        }
        Ok(())
    }

    async fn started(&self, _ctx: &mut Self::Context) -> Result<(), ActorError> {
        println!("[{}] Actor started", self.id);
        Ok(())
    }
}

#[tokio::test]
async fn test_full_system_integration() -> Result<()> {
    // 初始化日志系统
    protoactor_rs::logging::init_global_logger(Some(tracing::Level::DEBUG), None)?;

    // 创建 actor 系统
    let system = ActorSystem::new()?;

    // 创建带有中间件和监督策略的 Props
    let props = Props::new(Box::new(move || Box::new(TestActor {
        id: "test_actor".to_string(),
    })))
    .with_middleware(LoggingMiddleware::new())
    .with_supervisor(Strategies::restart_with_backoff(
        Duration::from_millis(100),
        Duration::from_secs(1),
        3,
    ))
    .with_dispatcher(Dispatchers::throughput(100));

    // 启动 actor
    let pid = system.spawn(props).await?;

    // 测试基本消息传递
    let response = system
        .request::<Pong>(&pid, Ping(1), Duration::from_secs(1))
        .await?;
    assert_eq!(response.0, 1);

    // 测试发布/订阅
    let topic = "test_topic";
    system.subscribe(&pid, topic).await?;
    system.publish(topic, Ping(2)).await?;

    // 等待消息处理
    tokio::time::sleep(Duration::from_millis(100)).await;

    // 测试优雅关闭
    system.stop(&pid).await?;
    
    // 验证系统状态
    assert!(!system.is_alive(&pid).await);

    Ok(())
}

// 测试集群功能
#[tokio::test]
async fn test_cluster_integration() -> Result<()> {
    use protoactor_rs::cluster::{ClusterConfig, ClusterProvider};
    
    // 创建两个集群节点
    let config1 = ClusterConfig::new("node1", "127.0.0.1:8001");
    let config2 = ClusterConfig::new("node2", "127.0.0.1:8002");

    let system1 = ActorSystem::new()?;
    let system2 = ActorSystem::new()?;

    // 启动集群
    let cluster1 = system1.start_cluster(config1).await?;
    let cluster2 = system2.start_cluster(config2).await?;

    // 等待集群同步
    tokio::time::sleep(Duration::from_secs(1)).await;

    // 验证集群成员
    assert_eq!(cluster1.members().await?.len(), 2);
    assert_eq!(cluster2.members().await?.len(), 2);

    Ok(())
}

// 测试流式处理
#[tokio::test]
async fn test_streaming() -> Result<()> {
    use protoactor_rs::streaming::{StreamSubscriber, StreamPublisher};
    use futures::StreamExt;

    let system = ActorSystem::new()?;

    // 创建流发布者和订阅者
    let publisher = StreamPublisher::new();
    let mut subscriber = StreamSubscriber::new();

    // 订阅流
    let mut stream = subscriber.subscribe(&publisher).await?;

    // 发布消息
    publisher.publish(Ping(1)).await?;
    publisher.publish(Ping(2)).await?;
    publisher.publish(Ping(3)).await?;

    // 验证接收到的消息
    let mut count = 0;
    while let Some(msg) = stream.next().await {
        count += 1;
        if count == 3 {
            break;
        }
    }

    assert_eq!(count, 3);

    Ok(())
}

// 测试监控系统
#[tokio::test]
async fn test_metrics() -> Result<()> {
    use protoactor_rs::metrics::{MetricsMiddleware, get_metrics};

    let system = ActorSystem::new()?;

    // 创建带有指标中间件的 actor
    let props = Props::new(Box::new(|| {
        Box::new(TestActor {
            id: "metrics_test".to_string(),
        })
    }))
    .with_middleware(MetricsMiddleware::new());

    let pid = system.spawn(props).await?;

    // 发送一些消息
    for i in 0..5 {
        system.send(&pid, Ping(i)).await?;
    }

    // 等待消息处理
    tokio::time::sleep(Duration::from_millis(100)).await;

    // 验证指标
    let metrics = get_metrics();
    assert!(metrics.message_count() > 0);
    assert!(metrics.actor_count() > 0);

    Ok(())
} 